/// @tags: MuoDuionTree
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>

using namespace std;

namespace BlueQuantum {

#define MAXN 111111
#define MAXC 222222
std::map<int, int> M;
int n, m, c[MAXN], CNT, nc[MAXN], ans[MAXN];

// Graph & index
int per;
int dfn[MAXN], dep[MAXN], fr[MAXN], ne[MAXN * 2], to[MAXN * 2], fa[MAXN][22], cnt;
int be[MAXN], siz[MAXN], stack[MAXN], top, Cnt;
void add(int a, int b) {
  ne[++cnt] = fr[a], fr[a] = cnt, to[cnt] = b;
  ne[++cnt] = fr[b], fr[b] = cnt, to[cnt] = a;
}  // ok
int dfs(int a) {
  dep[a] = dep[fa[a][0]] + 1;
  dfn[a] = ++cnt;
  int siz = 0;
  for (int i = fr[a]; i; i = ne[i]) {
    if (to[i] == fa[a][0]) continue;
    fa[to[i]][0] = a;
    siz += dfs(to[i]);
    if (siz >= per) {
      ++Cnt;
      while (siz--) be[stack[top--]] = Cnt;
    }
  }
  stack[++top] = a;
  return siz + 1;
}
int lca(int a, int b) {
  if (dep[a] < dep[b]) std::swap(a, b);
  int k = dep[a] - dep[b];
  for (int i = 0; i <= 17 && k; i++) {
    if (k & 1) a = fa[a][i];
    k >>= 1;
  }
  if (a == b) return a;
  for (int i = 17; i >= 0; i--)
    if (fa[a][i] != fa[b][i]) a = fa[a][i], b = fa[b][i];
  return fa[a][0];
}

// Query
int qn, mn, pa, pb, pt, Ans, s[MAXC];
bool vis[MAXN];
struct Q {
  int a, b, t;
} q[MAXN];
struct Data {
  int a, b, c, t;
} mo[MAXN];
void reverse(int a) {
  if (vis[a]) vis[a] = false, s[nc[a]]--, (s[nc[a]] == 0) && (Ans--);
  else
    vis[a] = true, (s[nc[a]] == 0) && (Ans++), s[nc[a]]++;
}
void change(int a, int b) {
  if (vis[a]) {
    reverse(a);
    nc[a] = b;
    reverse(a);
  } else
    nc[a] = b;
}
void solve(int a, int b) {
  while (a != b) {
    if (dep[a] > dep[b]) reverse(a), a = fa[a][0];
    else
      reverse(b), b = fa[b][0];
  }
}
void query(Q k) {
  int a = k.a, b = k.b, t = k.t, T = lca(a, b);
  while (mo[pt].t > t) change(mo[pt].a, mo[pt].b), pt--;
  while (mo[pt + 1].t < t && pt + 1 <= mn) pt++, change(mo[pt].a, mo[pt].c);
  solve(pa, a);
  solve(pb, b);
  pa = a, pb = b;
  reverse(T);
  ans[t] = Ans;
  reverse(T);
}

// else
bool cmpt(Data a, Data b) { return a.t < b.t; }
bool cmp(Q a, Q b) {
  if (be[a.a] == be[b.a] && be[a.b] == be[b.b]) return a.t < b.t;
  else if (be[a.a] == be[b.a])
    return be[a.b] < be[b.b];
  return be[a.a] < be[b.a];
}
void inputq() {
  for (int i = 1; i <= n; i++) nc[i] = c[i];
  for (int i = 1, op, a, b; i <= m; i++) {
    scanf("%d %d %d", &op, &a, &b);
    if (op == 1) {
      q[++qn] = (Q){a, b, i};
      if (be[a] > be[b]) std::swap(q[i].a, q[i].b);
    } else {
      if (M[b]) b = M[b];
      else
        b = M[b] = ++CNT;
      mo[++mn] = (Data){a, nc[a], b, i};
      nc[a] = b;
    }
  }
  std::sort(q + 1, q + qn + 1, cmp);
  std::sort(mo + 1, mo + mn + 1, cmpt);
  for (int i = 1; i <= n; i++) nc[i] = c[i];
}

// main
int main() {
  scanf("%d %d", &n, &m);
  per = pow(n, 2.0 / 3);
  for (int i = 1, a; i <= n; i++) {
    scanf("%d", &a);
    if (M[a]) c[i] = M[a];
    else
      c[i] = M[a] = ++CNT;
  }
  for (int i = 1, a, b; i < n; i++) scanf("%d %d", &a, &b), add(a, b);
  cnt = 0;
  dfs(1);
  while (top) be[stack[top--]] = Cnt;
  for (int i = 1; i <= 17; i++)
    for (int j = 1; j <= n; j++) fa[j][i] = fa[fa[j][i - 1]][i - 1];
  inputq();
  for (int i = 1; i <= qn; i++) query(q[i]);
  for (int i = 1; i <= m; i++)
    if (ans[i]) printf("%d\n", ans[i]);
  return 0;
}

}  // namespace BlueQuantum

int main() {
#ifndef ONLINE_JUDGE
#ifdef LOCAL
  freopen("/tmp/CodeTmp/testdata.in", "r", stdin);
  freopen("/tmp/CodeTmp/testdata.out", "w", stdout);
#else
  freopen("num.in", "r", stdin);
  freopen("num.out", "w", stdout);
#endif
#endif

  ios::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL);
  return BlueQuantum::main();
}
